package com.uatair.common.mqtt.uploader;

import com.uatair.common.mqtt.domain.dto.ApiUploadResponse;
import com.uatair.common.mqtt.domain.task.RecodeTask;
import com.uatair.common.mqtt.domain.task.SortieTask;
import com.uatair.common.mqtt.domain.task.TaskDTO;
import com.uatair.common.mqtt.domain.task.UavTask;
import com.uatair.common.mqtt.util.AESUtil;
import com.uatair.common.mqtt.util.ProtobufUtil;
import com.uatair.common.mqtt.util.UAesUtil;
import com.uatair.common.tcp.client.TianJinClientService;
import com.uatair.common.utils.uuid.IdUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.uatair.common.tcp.util.TianjinTcp;
import com.uatair.common.tcp.util.TianjinTcp.Message;
import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Component
public class TianJinTaskUploader {

    private static final Logger logger = LoggerFactory.getLogger(TianJinTaskUploader.class);

    private final TianJinClientService tcpClient;

    public TianJinTaskUploader(TianJinClientService tcpClient) {
        this.tcpClient = tcpClient;
    }

    public List<RecodeTask> putTianJinTask(TaskDTO taskDTO){
        List<RecodeTask> recodeTaskList = new ArrayList<>();
        for (UavTask uavTask : taskDTO.getUavTaskList()){
            RecodeTask uavInfoTask = uploadUavInfo(uavTask);
            ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, uavInfoTask);
        }
        if (!taskDTO.getSortieTaskList().isEmpty()){
            for (SortieTask sortieTask : taskDTO.getSortieTaskList()) {
                if (sortieTask.getPath() != null) {
                    List<String> strings = UAesUtil.downloadAndParseFile(sortieTask.getPath());
                    if (!strings.isEmpty()) {
                        List<UavTask> uavTaskList = taskDTO.getUavTaskList();
                        UavTask uavTask = new UavTask();
                        for (UavTask uavTask1 : uavTaskList)
                            if (Objects.equals(uavTask1.getSn(), sortieTask.getSn()))
                                uavTask = uavTask1;
                        List<JSONObject> traceJson = AESUtil.getJsonObjects(strings);
                        String uuid = IdUtils.simpleUUID();
                        RecodeTask recodeSorties = uploadFlightRecord(sortieTask, uuid, traceJson, uavTask);
                        RecodeTask recodeSortiesDetail = uploadFlightRecordDetail(sortieTask, uuid, traceJson, uavTask);
                        ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeSorties);
                        ZhiBaoYunTaskUploader.setTaskId(taskDTO, recodeTaskList, recodeSortiesDetail);
                    }
                }
            }
        }
        return recodeTaskList;
    }

    /**
     * 上传飞行记录
     *
     * @return
     */
    public RecodeTask uploadFlightRecord(SortieTask sortieTask, String uuid, List<JSONObject> traceJson, UavTask uavTask) {
        try {
            DecimalFormat df = new DecimalFormat("0.00");
            TianjinTcp.FlightRecord.Builder builder = TianjinTcp.FlightRecord.newBuilder()
                    .setUuid(uuid)
                    .setCollectTime(sortieTask.getStartTime().getTime())
                    .setWorkTime(sortieTask.getFlightTime().intValue())
                    .setStartEnd(TianjinTcp.TimeRange.newBuilder()
                            .setStart(sortieTask.getStartTime().getTime())
                            .setEnd(sortieTask.getEndTime().getTime())
                            .build())
                    .setCreatedAt(System.currentTimeMillis())
                    .setLocation(sortieTask.getPositionInfo())
                    .setPosition(TianjinTcp.Position.newBuilder()
                            .setLongitude(Double.parseDouble(traceJson.get(0).get("lon").toString()))
                            .setLatitude(Double.parseDouble(traceJson.get(0).get("lat").toString()))
                            .build())
                    .setWorkArea(Float.parseFloat(df.format(sortieTask.getSize()*0.0015)))
                    .setUsageType(Integer.parseInt(sortieTask.getOptMode()))
                    .setDroneType("3WWDZ-U50C")
                    .setHardwareId(uavTask.getSn())
                    .setBodyCode(uavTask.getCodeOfBodyFrame())
                    .setBatterySn(uavTask.getCodeOfGroundStation());

            for (int i = 0; i < traceJson.size(); i += 20) {
                int sprayType = 0;
                if (traceJson.get(i).has("workArea")) {
                    double workArea = Double.parseDouble(traceJson.get(i).get("workArea").toString());
                    sprayType = workArea > 1 ? workArea < sortieTask.getSize() ? 1 : 0 : 0;
                } else {
                    double alt = Double.parseDouble(traceJson.get(i).get("relativeAlt").toString());
                    if (alt > 3)
                        sprayType = 1;
                }
                builder.addSimplifyPoints(TianjinTcp.SimplifyPoint.newBuilder()
                        .setPosition(TianjinTcp.Position.newBuilder()
                                .setLongitude(Double.parseDouble(traceJson.get(i).get("lon").toString()))
                                .setLatitude(Double.parseDouble(traceJson.get(i).get("lon").toString()))
                                .build())
                        .setIsSpray("0".equals(sortieTask.getOptMode()) && sprayType == 1)
                        .setIsSow("1".equals(sortieTask.getOptMode()) && sprayType == 1)
                        .setWorkMode(0)
                        .build());
            }

            // 确保包含最后一个点
            if ((traceJson.size() - 1) % 20 != 0) {
                int sprayType = 0;
                if (traceJson.get(traceJson.size()-1).has("workArea")) {
                    double workArea = Double.parseDouble(traceJson.get(traceJson.size()-1).get("workArea").toString());
                    sprayType = workArea > 1 ? workArea < sortieTask.getSize() ? 1 : 0 : 0;
                } else {
                    double alt = Double.parseDouble(traceJson.get(traceJson.size()-1).get("relativeAlt").toString());
                    if (alt > 3)
                        sprayType = 1;
                }
                builder.addSimplifyPoints(TianjinTcp.SimplifyPoint.newBuilder()
                        .setPosition(TianjinTcp.Position.newBuilder()
                                .setLongitude(Double.parseDouble(traceJson.get(traceJson.size()-1).get("lon").toString()))
                                .setLatitude(Double.parseDouble(traceJson.get(traceJson.size()-1).get("lon").toString()))
                                .build())
                        .setIsSpray("0".equals(sortieTask.getOptMode()) && sprayType == 1)
                        .setIsSow("1".equals(sortieTask.getOptMode()) && sprayType == 1)
                        .setWorkMode("1".equals(sortieTask.getRouteMode())?4:0)
                        .build());
            }
            // 设置喷洒或播撒用量
            if ("0".equals(sortieTask.getOptMode())) {
                builder.setSprayUsage((int)Math.round(sortieTask.getDosage() * 1000));
            } else {
                builder.setSowUsage((int)Math.round(sortieTask.getDosage() * 1000));
            }

            TianjinTcp.FlightRecord flightRecord = builder.build();

            Message message = Message.newBuilder()
                    .setDataType(Message.DataType.FLIGHTRECORDTYPE)
                    .setVersion(Message.ProtocolVersion.V1_0_1)
                    .setFlightRecord(flightRecord)
                    .build();

            tcpClient.sendMessage(message);
            return setTianJinTcpTask(uavTask.getSn(), ProtobufUtil.toTianJinJson(message), "无人机飞行记录上报");
        } catch (Exception e) {
            logger.error("上传飞行记录失败", e);
            throw new RuntimeException("上传飞行记录失败", e);
        }
    }

    /**
     * 上传飞行记录明细
     *
     * @return
     */
    public RecodeTask uploadFlightRecordDetail(SortieTask sortieTask, String uuid, List<JSONObject> traceJson, UavTask uavTask) {
        try {
            TianjinTcp.FlightRecordDetail.Builder builder = TianjinTcp.FlightRecordDetail.newBuilder()
                    .setCount(traceJson.size())
                    .setUuid(uuid)
                    .setHardwareId(uavTask.getSn())
                    .setBodyCode(uavTask.getCodeOfBodyFrame())
                    .setStartEnd(TianjinTcp.TimeRange.newBuilder()
                            .setStart(sortieTask.getStartTime().getTime())
                            .setEnd(sortieTask.getEndTime().getTime())
                            .build());

            long startMillis = sortieTask.getStartTime().toInstant().toEpochMilli();
            long endMillis = sortieTask.getEndTime().toInstant().toEpochMilli();
            long totalMillis = endMillis - startMillis;
            double intervalMillis = (double) totalMillis / ((traceJson.size()==1?2:traceJson.size()) - 1);
            int optMode = Integer.parseInt(sortieTask.getOptMode());
            for (int i = 0; i < traceJson.size(); i++) {
                JSONObject osd = traceJson.get(i);
                int sprayType = 0;
                if (osd.has("workArea")) {
                    double workArea = Double.parseDouble(osd.get("workArea").toString());
                    sprayType = workArea > 1 ? workArea < sortieTask.getSize() ? 1 : 0 : 0;
                } else {
                    double alt = Double.parseDouble(osd.get("relativeAlt").toString());
                    if (alt > 3)
                        sprayType = 1;
                }
                long currentMillis;
                if (i == traceJson.size() - 1) {
                    // 最后一个点直接使用结束时间，避免浮点误差
                    currentMillis = endMillis;
                } else {
                    // 使用四舍五入来减少累积误差
                    currentMillis = startMillis + Math.round(i * intervalMillis);
                }
                TianjinTcp.FlightData.Builder dataBuilder = TianjinTcp.FlightData.newBuilder()
                        .setCollectTime(currentMillis)
                        .setPosition(TianjinTcp.Position.newBuilder()
                                .setLongitude(Double.parseDouble(osd.get("lon").toString()))
                                .setLatitude(Double.parseDouble(osd.get("lat").toString()))
                                .build())
                        .setVelocity(TianjinTcp.Velocity.newBuilder()
                                .setX(Float.parseFloat(osd.get("vx").toString()))
                                .setY(Float.parseFloat(osd.get("vy").toString()))
                                .setZ(Float.parseFloat(osd.get("vz").toString()))
                                .build())
                        .setHeight(Float.parseFloat(osd.get("alt").toString()))
                        .setWorkMode("1".equals(sortieTask.getRouteMode())?4:0)
                        .setSprayWidth(sortieTask.getLineSpacing().floatValue());
                // 设置喷洒或播撒信息
                if (optMode == 0) {
                    dataBuilder.setSprayInfo(TianjinTcp.SprayInfo.newBuilder()
                            .setSprayType(sprayType)
                            .setFlowSpeed(sortieTask.getPumpSpeed().intValue())
                            .setResidualPesticide(0)
                            .build());
                } else {
                    dataBuilder.setSowInfo(TianjinTcp.SowInfo.newBuilder()
                            .setSowType(sprayType)
                            .setSowMode(0)
                            .setTurnSpeed(0)
                            .setHatchSize(0)
                            .setSowSpeed(0)
                            .build());
                }
                builder.addData(dataBuilder.build());
            }
            TianjinTcp.FlightRecordDetail detail = builder.build();

            Message message = Message.newBuilder()
                    .setDataType(Message.DataType.FLIGHTRECORDDETAILTYPE)
                    .setVersion(Message.ProtocolVersion.V1_0_1)
                    .setFlightRecordDetail(detail)
                    .build();

            tcpClient.sendMessage(message);
            return setTianJinTcpTask(uavTask.getSn(), "明细数据量过大,只存uuid:"+uuid, "无人机飞行明细上报");
        } catch (Exception e) {
            logger.error("上传飞行记录明细失败", e);
            throw new RuntimeException("上传飞行记录明细失败", e);
        }
    }

    /**
     * 上传无人机信息
     *
     * @return
     */
    public RecodeTask uploadUavInfo(UavTask uavTask) {
        try {
            TianjinTcp.UavInfo uavInfo = TianjinTcp.UavInfo.newBuilder()
                    .setHardwareId(uavTask.getSn())
                    .setBodyCode(uavTask.getCodeOfBodyFrame())
                    .setUavMode("3WWDZ-U50C")
                    .setBdIdentification("Y")
                    .setCompanyCode("859")
                    .build();
            Message message = Message.newBuilder()
                    .setDataType(Message.DataType.UAVINFOTYPE)
                    .setVersion(Message.ProtocolVersion.V1_0_1)
                    .setUavInfo(uavInfo)
                    .build();
            tcpClient.sendMessage(message);
            return setTianJinTcpTask(uavTask.getSn(), ProtobufUtil.toTianJinJson(message), "无人机信息上报");
        } catch (Exception e) {
            logger.error("上传无人机信息失败", e);
            throw new RuntimeException("上传无人机信息失败", e);
        }
    }

    private RecodeTask setTianJinTcpTask(String sn, String msg, String requestType) {
        ApiUploadResponse apiUploadResponse = new ApiUploadResponse("", "", "TCP/IP", 200);
        JSONObject requestBody = new JSONObject();
        requestBody.put("sn", sn);
        requestBody.put("massage", msg);
        return ZhiBaoYunTaskUploader.getRecode(apiUploadResponse, requestBody, requestType);
    }
}
